import json

from flask import jsonify
from common.common import Response
from redis.commands.search.field import VectorField
from redis.commands.search.indexDefinition import IndexDefinition, IndexType
from common.logger_config import setup_logger
from common.common import get_vector_index_name
from util.redis_pool import RedisSingleton

logger = setup_logger(__name__)  # 获取日志对象


class IndexInfo:
    def __init__(self, indexName, count):
        self.indexName = indexName
        self.count = count  # doc count

    # 将对象转换为字典格式，以便返回 JSON 响应
    def to_dict(self):
        return {
            "indexName": self.indexName,
            "count": self.count
        }

    def to_json(self):
        return json.dumps(self.to_dict())


class IndexResponse:
    def __init__(self, indexName, status):
        self.indexName = indexName
        self.status = status

    # 将对象转换为字典格式，以便返回 JSON 响应
    def to_dict(self):
        return {
            "indexName": self.indexName,
            "status": self.status
        }


class IndexDataResponse:
    def __init__(self, indexName, status, count):
        self.indexName = indexName
        self.status = status
        self.count = count or 0

    # 将对象转换为字典格式，以便返回 JSON 响应
    def to_dict(self):
        return {
            "indexName": self.indexName,
            "status": self.status,
            "count": self.count
        }


def check_index_param(param):  # 索引创建入参检查
    if param and isinstance(param, list):
        if len(param) > 100:
            return jsonify(Response(20001, "param failure", None, "params length exceeds 100").to_dict()), 200
        for item in param:
            if not isinstance(item, str):
                return jsonify(Response(20001, "param failure", None, "index name is not str.").to_dict()), 200
            if not item.strip() or len(item) > 50:
                return jsonify(Response(20001, "param failure", None, "index name is blank or length > 50.").to_dict()), 200
        return jsonify(Response(200, "", None, "").to_dict()), 200
    else:
        return jsonify(Response(20001, "param failure", None, "index param is blank").to_dict()), 200


def create_vector_index(application_name, index_origin_name):
    create_result = False

    # 向量维度
    vector_dimension = 1024

    # 索引名称
    vector_index_name = get_vector_index_name(application_name, index_origin_name)
    logger.info(f"vector_index_name = {vector_index_name}")

    # 定义向量数据库的 Schema
    schema = (
        VectorField(
            "$",
            "FLAT",
            {
                "TYPE": "FLOAT32",
                "DIM": vector_dimension,
                "DISTANCE_METRIC": "COSINE",
            },
            as_name="vector",
        ),
    )

    definition = IndexDefinition(prefix=[vector_index_name], index_type=IndexType.JSON)

    try:
        # 使用 Redis 客户端实例根据上面的 Schema 和定义创建索引
        res = RedisSingleton().get_redis().ft(vector_index_name).create_index(
            fields=schema, definition=definition
        )

        logger.info(f"create index finish. index_name = {vector_index_name}, res = {res}")
        create_result = True
    except Exception as e:
        logger.error(f"create index error. index_name = {vector_index_name}, error = {e}")

    return create_result


def check_vector_index_exist(application_name, index_name):
    result = False
    vector_index_name = get_vector_index_name(application_name, index_name)
    try:
        existing_indexes = RedisSingleton().get_redis().execute_command("FT._LIST")
        logger.info(f"existing_indexes = {existing_indexes}")
        if vector_index_name in existing_indexes:
            result = True
    except Exception as e:
        logger.error(f"check index exist error. index_name = {vector_index_name}, error = {e}")

    return result


def delete_vector_index(application_name, index_name):
    result = False
    vector_index_name = get_vector_index_name(application_name, index_name)
    try:
        result = RedisSingleton().get_redis().ft(vector_index_name).dropindex(delete_documents=True)
    except Exception as e:
        logger.error(f"delete index error. index_name = {vector_index_name}, error = {e}")

    return result


def get_vector_index_info(application_name, index_name):
    vector_index_name = get_vector_index_name(application_name, index_name)
    index_info = IndexInfo(vector_index_name, 0)
    try:
        index_info_result = RedisSingleton().get_redis().ft(vector_index_name).info()
        logger.info(f"get index info result = {index_info_result}")
        if index_info_result:
            doc_count = index_info_result.get("num_docs", 0)
            setattr(index_info, "count", doc_count)
    except Exception as e:
        logger.error(f"delete index error. index_name = {vector_index_name}, error = {e}")

    return index_info

